home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-20
/
pmpsrc11.zip
/
AX25SUBR.C
< prev
next >
Wrap
Text File
|
1991-07-30
|
6KB
|
293 lines
/*
ax25subr.c -- General AX.25 subroutines
Poor Man's Packet (PMP)
Copyright (c) 1991 by Andrew C. Payne All Rights Reserved.
Permission to use, copy, modify, and distribute this software and its
documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
granted, provided that the above copyright notice appear in all copies.
The author makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
Andrew C. Payne
*/
/* ----- Includes ------ */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <alloc.h>
#include <bios.h>
#include <mem.h>
#include <ctype.h>
#include "pmp.h"
/* ----- Address Manipulation ----- */
/* SetAX25Addr(addr,s)
Given a string s in the form 'N8KEI-3', converts to ax25_addr format.
Returns TRUE if error.
*/
int SetAX25Addr(struct ax25_addr *a, char *s)
{
struct ax25_addr t;
int i;
/* check for empty string */
if(*s == NULL)
return TRUE;
for(i=0; i<MAXCLEN; i++) {
if(*s && *s != '-' && !isspace(*s))
t.call[i] = toupper(*s++) << 1;
else
t.call[i] = ' ' << 1; /* pad w/ spaces */
}
if(i > MAXCLEN && *s && *s != '-') /* call too long */
return TRUE;
if(*s == '-') {
i = atoi(s+1);
if(i > 15)
return TRUE; /* invalid ssid */
} else
i = 0; /* default */
t.ssid = 0x60 | (i << 1);
/* all is well, copy it into 'a' */
memcpy(a,&t,sizeof(struct ax25_addr));
return FALSE;
}
/* GetAX25Addr(addr)
Given a pointer to an ax25_addr record, returns an ASCII string of
the address in human readable form: 'N8KEI-3'
*/
char *GetAX25Addr(struct ax25_addr *a)
{
static char s[MAXCLEN+5];
char *p;
char c;
int i;
/* translate callsign */
p = s;
for(i=0; i<MAXCLEN; i++) {
c = (a->call[i] >> 1) & 0x7f;
if(c == ' ')
break;
else
*p++ = c;
}
/* copy ssid if non-zero */
i = (a->ssid >> 1) & 0x0f;
if(i)
sprintf(p,"-%d",i);
else
*p = '\0';
return s; /* return pointer to string */
}
/* CompAX25Addr(a1,a2)
Compares two AX.25 addresses. Returns TRUE if they are not equal.
*/
int CompAX25Addr(struct ax25_addr *a1, struct ax25_addr *a2)
{
/* compare the calls */
if(memcmp(a1->call,a2->call,sizeof(struct ax25_addr)-1))
return TRUE;
/* compare the SSIDs */
return (a1->ssid & 0x1e) != (a2->ssid & 0x1e);
}
/* ----- Address/Path Parsing ----- */
/* SetAX25Path(s)
Given a path string in the form "KC3BQ-3 v W2CXM-1,WB2EMS-1",
and a pointer to a ax25_packet structure, sets the destination
address records.
Returns TRUE if successful, FALSE if error.
*/
int SetAX25Path(char *s, struct ax25_packet *a)
{
char *p;
char t[80];
int i;
/* extract the destination callsign */
p = extract(s,t);
if(SetAX25Addr(&a->dest,t))
return FALSE;
/* Is there a digi path? */
a->ndigis = i = 0;
if(*p == '\0')
return TRUE; /* end of string, no digi path */
p = extract(p,t);
if(*t != 'v') /* expect VIA */
return FALSE;
/* extract digi path */
while(*p && i < MAXDIGIS) {
p = extract(p,t);
if(SetAX25Addr(a->digis+i,t))
return FALSE;
i++;
}
a->ndigis = i;
return i < MAXDIGIS;
}
/* GetAX25Path(*packet)
Given a pointer to a level 2 packet, parses, and returns a pointer to
a human readable string in the form:
"N8KEI [via WB2EMS]"
*/
char *GetAX25Path(struct ax25_packet *p)
{
static char s[80];
int i;
struct ax25_addr *ad;
/* copy in the destination call */
strcpy(s,GetAX25Addr(&p->dest));
/* copy in the digi path */
if(i = p->ndigis) {
strcat(s," [via ");
strcat(s,GetAX25Addr(p->digis));
ad = p->digis + 1;
while(i > 1) {
strcat(s,",");
strcat(s,GetAX25Addr(ad++));
i--;
}
strcat(s,"]");
}
return s;
}
/* ----- Reverse Path ----- */
/* ReversePath(p1,p2)
Given two AX.25 Level 2 packets, constructs the path in p1 as the
reverse of the path in p2.
*/
void ReversePath(struct ax25_packet *p1, struct ax25_packet *p2)
{
int i;
memcpy(&p1->dest,&p2->source,sizeof(struct ax25_addr));
memcpy(&p1->source,&p2->dest,sizeof(struct ax25_addr));
if(p1->ndigis = p2->ndigis) {
for(i=0; i<p2->ndigis; i++)
memcpy(p1->digis+i,p2->digis+(p2->ndigis - i - 1),
sizeof(struct ax25_addr));
}
}
/* ----- AX25 Packet Transmission ----- */
/* FrameType(control)
Given the control byte, returns the type of the frame.
*/
int FrameType(byte c)
{
if(!(c & 1))
return I; /* Information */
if(c & 2)
return c & ~PF; /* U frames, strip PF */
else
return c & 0xf; /* S frames */
}
/* CmdResp(p)
Given a pointer to a level1 packet, returns the command/response
type.
*/
int CmdResp(struct ax25_level1 *p)
{
byte *d;
d = p->data;
/* figure out control/response bits */
if(d[MAXCLEN + sizeof(struct ax25_addr)] & 0x80) {
if(d[MAXCLEN] & 0x80)
return UNKNOWN;
else
return RESPONSE;
} else {
if(d[MAXCLEN] & 0x80)
return COMMAND;
else
return UNKNOWN;
}
}
/* ----- Beacon ----- */
/* SendBeacon()
Sends the beacon message in 'btext' to the destination/path in
'baddr'.
*/
void SendBeacon(void)
{
struct ax25_packet *p;
/* allocate an ax25_packet structure */
if((p = malloc(sizeof(struct ax25_packet) + strlen(btext))) == NULL)
OutOfMemory();
/* build UI packet with beacon text */
memcpy(&p->source, &MyCall, sizeof(struct ax25_addr));
p->pid = PID_TEXT;
p->cont = UI;
SetAX25Path(baddr, p);
strcpy(p->data, btext);
p->dlen = strlen(btext);
SendAX25(p);
free(p);
}
/* StartBeacon()
If 'BeaconInt' is non-zero, starts the beacon timing interval.
*/
void StartBeacon(void)
{
if(BeaconInt)
BeaconEnd = BiosTime() + (BIOSSEC * BeaconInt);
else
BeaconEnd = 0;
}
/* ----- Send Welcome message ----- */
/* SendWelcome()
Sends the welcome message specified in CTEXT to incoming connects.
*/
void SendWelcome(void)
{
int i;
if(nctexts) {
for(i=0; i<nctexts; i++)
LinkSend(ctext[i],strlen(ctext[i]));
}
}